package com.demo.aidroid.util;

import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.future.Future;
import com.koushikdutta.async.http.AsyncHttpClient;
import com.koushikdutta.async.http.WebSocket;

import java.util.ArrayList;
import java.util.List;

import static com.demo.aidroid.App.getWebSocketServer;


public final class WebSocketTool implements AsyncHttpClient.WebSocketConnectCallback {
    public final static int TYPE_CONNECT = 0;
    public final static int TYPE_DISCONNECT = 1;
    public final static int TYPE_EXCEPTION = -1;
    public final static int TYPE_DATA = 2;

    private static WebSocketTool tool;
    private static List<Messenger> messengers = new ArrayList<>();

    static {
        tool = new WebSocketTool();
    }

    public static void RegisterMessageCallback(Messenger messenger) {
        messengers.add(messenger);
    }

    public static void RemoveMessageCallback(Messenger messenger) {
        messengers.remove(messenger);
    }

    private Future<WebSocket> webSocket;

    private WebSocketTool() {
        doConnect();
    }

    public static void Connect() {
        tool.doConnect();
    }

    public static void Disconnect() {
        tool.doDisconnect();
    }

    private void doConnect() {
        try {
            webSocket = AsyncHttpClient.getDefaultInstance().websocket("ws://" + getWebSocketServer() + ":3001", null, this);
        } catch (Exception ex) {
            ex.printStackTrace();
            SendMessage(TYPE_EXCEPTION, ex.getMessage());
        }

    }

    private void doDisconnect() {
        if (webSocket != null && !webSocket.isCancelled())
            webSocket.cancel();
        SendMessage(TYPE_DISCONNECT, "DisConnect");
    }

    @Override
    public void onCompleted(Exception ex, WebSocket webSocket) {
        if (ex != null) {
            ex.printStackTrace();
            SendMessage(TYPE_EXCEPTION, ex.getMessage());
            return;
        }

        SendMessage(TYPE_CONNECT, "Connect");
//        webSocket.send("laptop001");

        webSocket.setClosedCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                Log.d("Closed Callback:", ex.getMessage());
                SendMessage(TYPE_DISCONNECT, "DisConnect");
            }
        });
        webSocket.setEndCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                Log.d("end Callback:", ex.getMessage());
            }
        });
        webSocket.setStringCallback(new WebSocket.StringCallback() {
            public void onStringAvailable(String s) {
                SendMessage(TYPE_DATA, s);
            }
        });
    }

    public static void Send(String message) {
        try {
            if (tool.webSocket != null)
                tool.webSocket.tryGet().send(message);
        } catch (Throwable tr) {
            Log.e("Service", "", tr);
        }
    }

    private void SendMessage(int type) {
        SendMessage(type, null);
    }

    private void SendMessage(int type, String data) {
        Message msg = Message.obtain();
        msg.what = type;

        if (data != null)
            msg.obj = data;

        for (Messenger messenger : messengers) {
            try {
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}
